/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
/**
 * \file
 * \brief GIMnetAP Multicast service protocol header.
 * \author Antti Maula <antti.maula@tkk.fi>
 *
 * Simple multicast mechanism built on top of fastProtocol. A few key issues:
 * - Multicast core is operating over fastProtocol
 * - Requests are received from any node
 * - Subscriptions are only allowed from sourcenodes (Cannot register other nodes as receivers)
 * - Publishing is private or public
 *   - Private publishing means that only the original registrant may send data
 *   - Public publishing means that anybody may send data to service, which is then sent to everybody in the group.
 *   - Anybody can publish
 * - Data is sent point-to-point to a multicast service, which reads the payload multicast header;
 *   
 * - Spex:
 *   - 
 *
 */
#ifndef _GIMNETAP_MULTICASTFRAME_H_
#define _GIMNETAP_MULTICASTFRAME_H_

#include <inttypes.h>

/// Multicast service type
#define GIMNETAP_SERVICE_MULTICAST_ID    0x0102


/// Service request types.
enum EAPMulticastRequest {

  /** Create and reserve a new Multicast Id.
   */
  KAPMulticastRequestCreateMulticastId     = 0x01,

  /** Publish a new Multicast queue.
   *
   */
  KAPMulticastRequestPublishPublic         = 0x02,

  /**
   */
  KAPMulticastRequestPublishPrivate        = 0x03,

  /**
   */
  KAPMulticastRequestUnpublish             = 0x04,

  /**
   */
  KAPMulticastRequestSubscribe             = 0x05,

  /**
   */
  KAPMulticastRequestUnsubscribe           = 0x06,


  /** This request returns a list of existing Multicast Ids.
   *
   */
  KAPMulticastRequestIdList                = 0x07,


  /**
   */
  KAPMulticastRequestMulticast             = 0x0A
};


/// Service flag types (These are binary flags which can be set/unset
/// separately)
enum EAPMulticastFlag {

  /** Carried message is a reply.
   */
  /// Message is a Reply
  KAPMulticastFlagReply                    = (1<<0),

  /// Service replies to MulticastPayload with the number of delivered messages
  /// in 'result' field of MulticastCtrl.
  KAPMulticastFlagWantDeliveryCount        = (1<<1) 
};


/// Service result codes.
enum EAPMulticastResult {
  KAPMulticastResultOK                = 0x01,
  KAPMulticastResultIdNotFound        = 0x02,
  KAPMulticastResultAccessDenied      = 0x03,
  KAPMulticastResultFailedUnknown     = 0xff
};


/** Common header for all multicast frames. Only minimal information
 *  included.
 */
typedef struct SAPMulticastFrame
{
  // 4 bytes
  uint16_t service_id;          ///< Service identifier
  uint8_t request;              ///< Type of request
  uint8_t flags;                ///< Flags.
  uint32_t identifier;          ///< Frame Identifier - Unique on sender side.

} TAPMulticastFrame;
#define SIZEOF_TAPMULTICASTFRAME (8)

/** Setup data.
 *
 */
typedef struct SAPMulticastCtrl
{
  uint32_t multicast_id;
  uint32_t result;
  uint64_t owner_key;
  uint64_t access_key;

} TAPMulticastCtrl;
#define SIZEOF_TAPMULTICASTCTRL (24)

/** Payload data.
 *
 */
typedef struct SAPMulticastPayload
{
  uint32_t multicast_id;        ///< Multicast circuit identifier
  uint64_t access_key;
  uint8_t payload[];
} __attribute__((packed, aligned (4))) TAPMulticastPayload; 
#define SIZEOF_TAPMULTICASTPAYLOAD (12)

#endif
